<?php

abstract class stg_Object
{
	protected $_ID;
	protected $_name;
	protected $_universe;
	protected $_class_name = 'OBJECT'; 
	protected $__permissions = array();
	
	public function construct($name)
	{
		$this->name = $name;
		e("Building {$this->complete_name}");
		$this->add_permission('universe', 'stg_Universe');
		$this->add_permission('ID', 'stg_Universe');
	}
	
	public function get_complete_name()
	{
		return "{$this->class_name} {$this->name}";
	}

	protected function add_permission($property /* as string */, $class /* as string */)
	{
		if (!array_key_exists($property, $this->__permissions)) {
			 $this->__permissions[$property] = array();
		}
		
		$this->__permissions[$property][] = $class;
	}
	public function execute($order)
	{

		// Knowledge condition
		if (!$this->is_known_by($order->player))
			throw new Exception("{$order->player->name} does not know {$this->complete_name}");

		// Active object condition
		if (!$this->is_active)
			throw new Exception("{$this->complete_name} is not active");

		// Ownership condition
		if (!$this->is_owned_by($order->player))
			throw new Exception("{$this->complete_name} is not owned by {$order->player->name}");

		// Action condition
		if (!method_exists($this, $order->action))
			throw new Exception("{$this->complete_name} has not a command named $order->action");

		// Precondition


		// EXECUTE!!!
		call_user_func_array(array(&$this, $order->action), $order->arguments);
	}

	public function& __get($name)
	{
		if (method_exists($this, "get_$name"))
		{
			$result = call_user_func(array(&$this, "get_$name"));
			return $result;
		}
		elseif (property_exists($this, "_$name"))
		{
			return $this->{"_$name"};
		}
		else
		{
			throw new Exception("Property $name does not exist in class ".get_class($this)."!!");
		}
	}

	public function __set($name, $val)
	{
		if (array_key_exists("_$name",get_object_vars($this)))
		{
			$caller_class = get_caller_class();
			$caller_object = get_caller_object();
			if (property_exists($this, '__permissions'))
			{
				$perms = $this->__permissions;
			}
			else
			{
				$perms = array();
			}
			// Who can write this property?
			// 1. Objects of this class
			// 2. Objects of a parent class of this
			// 3. Authorized objects
			if  (
			    get_class($this) == $caller_class ||
				is_subclass_of($this, $caller_class) ||
			    is_writable_by($caller_object, $perms, $name)
				)
			{
				if (method_exists($this, "set_$name"))
				{
					call_user_func(array(&$this, "set_$name"), $val);
				}
				else
				{
					$this->{"_$name"} = $val;
				}
			}
			else
			{
				throw new Exception("Property $name in class ".get_class($this)." is not writable by ".get_caller_class()." instances");
			}
		}
		else
		{
			throw new Exception("Property $name does not exist in class ".get_class($this)."!!");
		}
	}

// KNOWN OBJECTS

	protected $_is_all_known = false;
	
	public function is_known_by($player /* as Player */)
	{
		if ($this->is_owned_by($player)) {
			return true;
		}
		
		if ($this->is_all_known)
		{
			return true;
		}
		
		if (in_array($this, $player->known_universe->objects))
		{
			return true;
		}
		return false;
	}

	// ACTIVE OBJECTS

	protected $_is_active = false;

	protected $_queue = array();
	protected $_owners = array();

	public function get_allowed_commands()
	{
		if (!$this->is_active) {
			throw new Exception('Invalid operation on non-active objects');
		}
		return array();
	}
	
	public function add_command($cmd /* as Command */) {
		if (!$this->is_active) {
			throw new Exception('Invalid operation on non-active objects');
		}
		$this->_queue[] = $cmd;
	}

	public function add_owner($owner /* as Player */)
	{
		if (!$this->is_active) {
			throw new Exception('Invalid operation on non-active objects');
		}
		$this->_owners[] = $owner;
		e("Player {$owner->name}[{$owner->ID}] is now owner of {$this->name}[{$this->ID}]");
	}

	public function is_owned_by($owner /* as Player */)
	{
		return in_array($owner, $this->_owners);
	}

// MOBILE OBJECTS
	protected $_is_mobile = false;
	
	protected $_desired_velocity;
	protected $_target;
	protected $_resources_consumed;
	protected $_estimated_destination;
	
	public function move() {
		if (!$this->is_mobile) {
			throw new Exception('Invalid operation on non-mobile objects');
		}

	}

// POSITIONABLE OBJECTS

	protected $_is_positionable = false;
	protected $_position;

}

?>
